import json
import logging
import time
import traceback

import rel
import websocket

from model.ReqRouterCommandEnum import ReqRouterCommandEnum
from model.WebsocketClientVO import WebsocketClientVO
from service.ArpService import ArpService
from service.ClashService import ClashService
from service.RouterDeviceService import RouterDeviceService
from service.UploadDataService import UploadDataService


class ClashTrafficWebSocketClientService:
    def __init__(self, clientVo: WebsocketClientVO):
        self.clientVo = clientVo
        self.updateDataService = UploadDataService(clientVo)
        self.routerDeviceService = RouterDeviceService(clientVo.dev)
        self.arpService = ArpService(clientVo)
        self.clashService = ClashService(self.clientVo)

    def onMessage(self, ws, message):
        try:
            if not message:
                return
            data = json.loads(message)
            if 'up' not in data or 'down' not in data:
                return
            a = self.arpService.lanMacList()
            p = self.clashService.getCurrentProxyFormClash()
            net = {
                'up': data['up'],
                'down': data['down'],
                'lan': a,
                'lan_count': a.__len__(),
            }
            net.update(p)
            result = {
                'device_id': self.clientVo.clientInfo,
                'net': net
            }
            if not self.clientVo.dev:
                result.update(self.routerDeviceService.deviceInfo())
            self.updateDataService.upload(
                result, ReqRouterCommandEnum.UPLOAD_ROUTER_DEVICE_INFO
            )
        except Exception as e:
            traceback.print_exc()

    def onError(self, ws, error):
        print(f"发生错误: {error}")

    def onClose(self, ws, closeStatusCode, closeMsg):
        print("连接已关闭")
        self.start()

    def onOpen(self, ws):
        pass

    def start(self):
        while True:
            try:
                target = self.clientVo.clashHost.replace("http", "ws") + 'traffic?token={}&level=info'.format(
                    self.clientVo.clashToken)
                self.ws = websocket.WebSocketApp(target,
                                                 on_open=self.onOpen,
                                                 on_message=self.onMessage,
                                                 on_error=self.onError,
                                                 on_close=self.onClose,
                                                 )
                self.clientVo.clashWs = self.ws
                self.ws.run_forever(dispatcher=rel, reconnect=5)
                break
            except Exception as e:
                logging.exception(e)
                time.sleep(30)
